package net.pimpas.web.jsf.resourcemanager;

import java.io.IOException;
import java.io.InputStream;
import java.util.Calendar;
import java.util.Date;

import javax.servlet.ServletContext;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.pimpas.logging.serviceprovider.LoggingServiceProvider;
import net.pimpas.logging.serviceprovider.LoggingServiceProviderFactoryImpl;

public class ResourceLoader implements org.apache.myfaces.renderkit.html.util.ResourceLoader {

	private static final LoggingServiceProvider logger = LoggingServiceProviderFactoryImpl.getLoggingServiceProvider(ResourceLoader.class);

	public void serveResource(ServletContext context, HttpServletRequest request,
			HttpServletResponse response, String resource) throws IOException {

		logger.debug("[RESOURCE LOADER]: Processing resource ("+resource+")");
		String[] uriParts = resource.split("/", 2);
		Class clazz = null;
		try {
			clazz = Class.forName(uriParts[0]);
		} catch (ClassNotFoundException e) {
			logger.error("[RESOURCE LOADER]: Can't find component class.", e);
			return;
		}
		
		InputStream input = clazz.getResourceAsStream(uriParts[1]);

		if(input == null) {
			logger.error("[RESOURCE LOADER]: Can't find resource ("+resource+")");
			response.sendError(HttpServletResponse.SC_NOT_FOUND, "Unable to find resource "
					+ resource + " "+ resource
					+ ". Check that this file is available " + "in the classpath in sub-directory "
					+ "/resource of the package-directory.");
			return;
		}
		// process output
		response.setContentType(this.getContentType(request, response, resource));
		// process cash
		this.processCaching(request, response, resource);
		// write
		this.writeResponse(response, input);
		
	}

	private void writeResponse(HttpServletResponse response, InputStream input) throws IOException {
		ServletOutputStream output = response.getOutputStream();
		int size;
		byte[] bytes = new byte[1024];
		while((size=input.read(bytes))!=-1)
			output.write(bytes, 0, size);
		// flush;
		output.flush();
		// close
		output.close();
	}

	private void processCaching(HttpServletRequest request, HttpServletResponse response, String resource) {
        response.setDateHeader("Last-Modified", getLastModified());
        Calendar expires = Calendar.getInstance();
        expires.add(Calendar.DAY_OF_YEAR, 7);
        response.setDateHeader("Expires", expires.getTimeInMillis());
	}

	private String getContentType(HttpServletRequest request, HttpServletResponse response, String resource) {
        if (resource.endsWith(".js"))
            return org.apache.myfaces.shared_tomahawk.renderkit.html.HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT;
        else if (resource.endsWith(".css"))
            return org.apache.myfaces.shared_tomahawk.renderkit.html.HTML.STYLE_TYPE_TEXT_CSS;
        else if (resource.endsWith(".gif"))
            return "image/gif";
        else if (resource.endsWith(".png"))
            return "image/png";
        else if (resource.endsWith(".jpg") || resource.endsWith(".jpeg"))
            return "image/jpeg";
        else if (resource.endsWith(".xml") || resource.endsWith(".xsl"))
            return "text/xml";
        
        // default
        return "text/html";
	}

	private static long getLastModified() {
		/*
		long lastModified;
		final String format = "yyyy-MM-dd HH:mm:ss";
		final String bundleName = ResourceManager.class.getName();
		ResourceBundle resources = ResourceBundle.getBundle(bundleName);
		String sLastModified = resources.getString("lastModified");
		try
		{
			lastModified = new SimpleDateFormat(format).parse(sLastModified).getTime();
		}
		catch (ParseException e)
		{
			lastModified = new Date().getTime();
			logger.error("Unparsable lastModified : " + sLastModified);
		}

		return lastModified;
		*/
		return new Date().getTime();
	}
}